#ifndef __CORE_COMMON_MULTI_THREAD_H_INCLUDE__
#define __CORE_COMMON_MULTI_THREAD_H_INCLUDE__

#include <core/common/platform.h>

//
// core::common::Thread usage
//
/**
class SampleThread : public core::common::Thread
{
private:
	virtual void run()
	{
		// thread runtime, do some things
		while( enabled_ )
		{
			// .....
		}
	}

public:
	SampleThread(){}
	virtual ~SampleThread(){}
};

SampleThread newThread;

// start
if( !newThread.start() )
{
	__ULOG_ERROR(__ULOG_FMT_ERR("SampleThread", "Start sample thread failed"), __UERR_CODE, __UERR_STR);
	return;
}

// stop
newThread.stop();
while( newThread.isRunning() )
{
	//....
}

// or stopAndJoin
newThread.stopAndJoin();

// auto delete thread
class AutoDeleteThread : public core::common::Thread
{
public:
	AutoDeleteThread()
	{
		autoDelete_ = true;
		autoDeleteCallback_ = AutoDeleteThread::deleteThread;
	}

	virtual ~AutoDeleteThread(){}

	static void deleteThread( void *param )
	{
		common::Thread *thread = (common::Thread *)param;
		delete thread;
	}
};

AutoDeleteThread *newThread = new AutoDeleteThread();
if( !newThread->start() )
{
	delete newThread;
}
**/

namespace core{ namespace common
{
	class CORE_COMMON_API__ Mutex
	{
		DISALLOW_COPY_AND_ASSIGN(Mutex);

		friend class Event;
	private:
		bool valid_;
		std::string name_;

#ifdef OS_PLATFORM_WINDOWS
		//mutable CRITICAL_SECTION object_;
		mutable HANDLE object_;
#else
		mutable pthread_mutex_t object_;
#endif

	public:
		Mutex();
		explicit Mutex( const std::string &name );
		virtual ~Mutex();

		bool create();
		bool create( const std::string &name );
		bool close();
		bool isValid() const;
		bool lock() const;
		bool tryLock() const;
		bool unlock() const;
	};

#ifndef ANDROID
	class CORE_COMMON_API__ ReadWriteMutex
	{
		DISALLOW_COPY_AND_ASSIGN(ReadWriteMutex);

	private:
#ifdef OS_PLATFORM_WINDOWS
		mutable bool lockedReader_;
		mutable int  readerCount_;
		mutable CRITICAL_SECTION reader_;
		mutable CRITICAL_SECTION writer_;
		mutable HANDLE noReaderEvent_;
		mutable HANDLE writerEvent_;

		inline void incReaderCount() const;
		inline void decReaderCount() const;
#else
		mutable pthread_rwlock_t object_;
#endif

	public:
		ReadWriteMutex();
		virtual ~ReadWriteMutex();

		bool readLock() const;
		bool writeLock() const;
		bool tryReadLock() const;
		bool tryWriteLock() const;
		bool unlock() const;
	};
#endif

	class CORE_COMMON_API__ AutoLock
	{
		DISALLOW_COPY_AND_ASSIGN(AutoLock);

	private:
		const Mutex *mutex_;
		mutable bool locked_;

	public:
		AutoLock( const Mutex *mutex, bool initLock = true );
		AutoLock( const Mutex &mutex, bool initLock = true );
		~AutoLock();

		bool lock() const;
		bool unlock() const;
	};

#ifndef ANDROID
	class CORE_COMMON_API__ AutoReadLock
	{
		DISALLOW_COPY_AND_ASSIGN(AutoReadLock);

	private:
		const ReadWriteMutex *mutex_;
		mutable bool locked_;

	public:
		AutoReadLock( const ReadWriteMutex *mutex, bool initLock = true );
		~AutoReadLock();

		bool lock() const;
		bool unlock() const;
	};

	class CORE_COMMON_API__ AutoWriteLock
	{
		DISALLOW_COPY_AND_ASSIGN(AutoWriteLock);

	private:
		const ReadWriteMutex *mutex_;
		mutable bool locked_;

	public:
		AutoWriteLock( const ReadWriteMutex *mutex, bool initLock = true );
		~AutoWriteLock();

		bool lock() const;
		bool unlock() const;
	};
#endif

	class CORE_COMMON_API__ Event
	{
		DISALLOW_COPY_AND_ASSIGN(Event);

	private:
		bool valid_;
		std::string name_;
		mutable uint32 error_;
#ifdef OS_PLATFORM_WINDOWS
		HANDLE object_;
#else
		Mutex locker_;
		mutable pthread_cond_t object_;
#endif

	public:
		Event();
		explicit Event( const std::string &name );
		virtual ~Event();

		bool create();
		bool create( const std::string &name );
		bool close();
		bool isValid() const;
		bool wait( int timeoutMs ) const;
		bool serviceWait( int timeoutMs ) const;
		bool trigger() const;
		bool reset() const;
		bool broadcast() const;
		bool isTimeout() const;
	};

	typedef void (* THREAD_INIT_NOTIFY_CALLBACK)();
	typedef void (* THREAD_EXIT_NOTIFY_CALLBACK)();
	typedef void (* THREAD_DELETE_CALLBACK)( void *pParam );
	typedef std::list<void *> ThreadNotifyCallbacks;

	class CORE_COMMON_API__ ThreadHelper
	{
	public:
		static THREAD_INIT_NOTIFY_CALLBACK initNotifier_;
		static THREAD_EXIT_NOTIFY_CALLBACK exitNotifier_;

		static void registerNotify( THREAD_INIT_NOTIFY_CALLBACK initNotifier, THREAD_EXIT_NOTIFY_CALLBACK exitNotifier );
	};

	class CORE_COMMON_API__ Thread
	{
		DISALLOW_COPY_AND_ASSIGN(Thread);

	protected:
#ifdef OS_PLATFORM_WINDOWS
		static const HANDLE kInvalidHandle;
		HANDLE object_;
#else
		static const pthread_t kInvalidHandle;
		pthread_t object_;
#endif
		bool    enabled_;
		bool    running_;
		int     threadStackSize_; // bytes
		int     threadPriority_;  // 1-99
		int     threadPolicy_;    // 
		size_t  threadId_;

		bool    autoDelete_;
		THREAD_DELETE_CALLBACK autoDeleteCallback_;

		Thread();

#ifdef OS_PLATFORM_WINDOWS
		static uintptr_t __STDCALL threadWrapper( void *pParam );
#else
		static void *threadWrapper( void *pParam );
#endif
		virtual void run() = 0;

	public:
		virtual ~Thread();
		virtual bool start();
		virtual bool stop();
		virtual bool stopAndJoin();
		virtual bool terminate();
		virtual bool isRunning() const;
		inline  bool isEnabled() const{ return enabled_; }
		inline  bool isObjectValid() const{ return Thread::kInvalidHandle != object_; }
		inline  size_t getThreadId() const{ return threadId_; }
		inline  void setThreadStackSize( int size ){ threadStackSize_ = size; }
		inline  void setThreadPriority( int priority ){ threadPriority_ = priority; }
		inline  void setThreadPolicy( int policy ){ threadPolicy_ = policy; }
		inline  int  getThreadStackSize() const{ return threadStackSize_; }
		inline  int  getThreadPriority() const{ return threadPriority_; }
		inline  int  getThreadPolicy() const{ return threadPolicy_; }

		static void   sleep( int millSecs );
		static size_t getCurrentId();
	};

	typedef std::list<Thread *>   ThreadPtrList;
	typedef std::vector<Thread *> ThreadPtrArray;

	class RunnableThread;

	class CORE_COMMON_API__ IRunnable
	{
	public:
		IRunnable(){}
		virtual ~IRunnable(){}

		virtual void run( core::common::RunnableThread *runnableThread ) = 0;
		virtual void stop() = 0;
	};

	class CORE_COMMON_API__ RunnableThread : public core::common::Thread
	{
	private:
		size_t runnableId_;
		core::common::IRunnable *runnable_;

		virtual void run();

	public:
		explicit RunnableThread( core::common::IRunnable *runnable );
		explicit RunnableThread( size_t runnableId, core::common::IRunnable *runnable );
		virtual ~RunnableThread();
		
		inline size_t getRunnableId(){ return runnableId_; }
		core::common::IRunnable *attach( core::common::IRunnable *runnable ); 
		virtual bool stop();
	};
}}

#endif //__CORE_COMMON_MULTI_THREAD_H_INCLUDE__
